<?php
declare (strict_types=1);

namespace app\course\logic\record;

use app\common\library\Queue;
use ArrayObject;
use app\course\logic\base\{Course, CourseSection, CourseStudent};
use app\course\model\record\{LearnCourseFinished, LearnCourseRate, LearnCourseRecord, LearnDailyRecord};

/**
 * 学习记录逻辑类
 */
class LearnRecord extends LearnCourseRecord
{

    /**
     * 添加学习记录
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date：   2020-05-13
     */
    public function addLearnRecord($param): void
    {
        // 验证数据
        $this->getValidate()->scene('add')->failException()->check($param);

        $param['mid']  = request()->mid;
        $param['time'] = time();
        if (request()->mid) Queue::push('LearnRecord', $param);
    }

    /**
     * app学习页面、pc学习中心概况
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date：   2020-05-15
     */
    public function fetchRecord(): array
    {
        $basic       = $this->getBasicRecord();
        $device_type = request()->device_type;
        $is_pc       = $device_type == 'pc';
        if ($is_pc) {
            $latest = $this->getLatestLearnCourse();
        } else {
            $latest = $this->getLatestLearnSection();
        }
        return ['basic' => $basic, 'latest' => $latest];
    }

    /**
     * 学习记录基础信息
     * Author   亓官雨树<lucky.max@foxmail.com>
     * Date 2020-05-14
     */
    public function getBasicRecord()
    {
        $info = app(LearnDailyRecord::class)->scope('mid')->findOrEmpty()->hidden(['id', 'user_id']);
        if ($info->isEmpty()) {
            $info = new ArrayObject();
        } else {
            $today = strtotime(date('Y-m-d'));
            if ($info->update_time < $today) {
                $info->today_learn_time = 0;
            } else {
                $info->today_learn_time = floor($info->today_learn_time / 60);
            }
            // $info->total_learn_time = round($info->total_learn_time / 3600, 2) * 1;

            // 连续学习天数
            if ($info->update_time + 86400 < $today) {
                $info->days = 0;
            }
            // 本周学习时长
            $start = strtotime(date('Y-m-d', (time() - ((date('w') == 0 ? 7 : date('w')) - 1) * 24 * 3600)));// 周一
            $end   = ($start+86400*7)-1;// 周日
            if ($info->update_time < $start || $info->update_time > $end) {
                $info->week_learn_time = 0;
            } else {
                $info->week_learn_time = floor($info->week_learn_time / 60);
            }

            $device_type = request()->device_type;

            $is_app = $device_type == 'android' || $device_type == 'ios';

            if (!$is_app) {
                $info->course_count = $this->scope('mid')->group('course_id')->count();
            }
        }

        return $info;
    }

    /**
     * 最近在学课程
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date：   2020-05-15
     */
    protected function getLatestLearnCourse()
    {
        $latest = $this->field('id,course_id,course_type')->scope('mid')->order('update_time', 'DESC')->group('course_id')->limit(8)->select()->append(['course_data'])->toArray();

        foreach ($latest as &$item) {
            $item['finished_rate'] = $this->calculateRate($item['course_id'], $item['course_type']);
            $item['expire_rest']   = app(CourseStudent::class)->getTermRest($item['course_id']);
        }

        return $latest;
    }

    /**
     * 最近在学课时
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date：   2020-05-15
     */
    protected function getLatestLearnSection(): array
    {
        $latest = $this->field('id,course_id,section_id,current_time,total_time,course_type,section_data_type')->scope('mid')->where('course_type', 1)->with(['section_title'])->order('update_time', 'DESC')->append(['course_data', 'sectionStock'])->limit(5)->select()->toArray();

        foreach ($latest as &$item) {
            $this->calculateRate($item['course_id'], $item['course_type']);
            $item['expire_rest'] = app(CourseStudent::class)->getTermRest($item['course_id']);
        }

        return $latest;
    }

    public function getCourseRate($course_id): int
    {
        $rate = app(LearnCourseRate::class)->scope('mid')->where('course_id', $course_id)->value('rate');
        return $rate ?: 0;
    }

    /**
     * 计算课程完成率
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date：   2020-05-15
     */
    public function calculateRate($course_id, $course_type, $mid = 0)
    {
        $mid = $mid ?: request()->mid;
        // 当前用户此课程学习进度总时间
        // $current_times  = $this->unfinished($course_id)->sum('current_time'); /* 20211009 完成条件又%调整为分钟数 */
        $total_time = $this->unfinished($course_id)->sum('total_time');
        // 当前用户此课程课时总时间
        $total_duration = $this->unfinished($course_id)->sum('section_duration');
        // 当前用户此课程已完成的课时
        $finished = $this->finished($course_id)->count();
        // 未完成课时进度
        $unfinished_rate = $total_duration ? round($total_time / $total_duration, 2) : 0;
        // 总课时
        $section_count = app(CourseSection::class)->getCourseSectionCount($course_id);
        // 课程进度
        $finished_rate = $section_count ? ($finished * 100 + $unfinished_rate * 100) / $section_count : 0;
        // 已完成的课程
        if ($finished_rate === 100) {
            $exist = app(LearnCourseFinished::class)->where([
                'user_id'   => $mid,
                'course_id' => $course_id,
            ])->findOrEmpty();
            if ($exist->isEmpty()) {
                LearnCourseFinished::create([
                    'user_id'   => $mid,
                    'course_id' => $course_id,
                ]);
            }
            $rate = 100;
        } else {
            $rate = ceil($finished_rate);
            $rate = $rate == 100 ? 99 : $rate;
        }
        $rate_data = app(LearnCourseRate::class)->scope('mid')->where('course_id', $course_id)->findOrEmpty();
        if ($rate_data->isEmpty()) {
            LearnCourseRate::create([
                'user_id'     => $mid,
                'course_id'   => $course_id,
                'course_type' => $course_type,
                'rate'        => $rate
            ]);
        } else {
            $rate_data->rate = $rate;
            $rate_data->save();
        }

        return $rate;
    }

    /**
     * 加入的课程
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date：   2020-05-18
     */
    public function getCourseList($param): array
    {
        // 验证数据
        $this->getValidate()->scene('course')->failException()->check($param);
        // 参数
        $course_type = $param['course_type'];
        $order       = strtolower($param['order'] ?? 'Add');
        // 查询
        $func            = 'getRecently' . ucfirst($order) . 'ed';
        $list['normal']  = $this->$func($course_type);
        $list['expired'] = $this->$func($course_type, true);

        return $list;
    }

    /**
     * 最近加入课程优先
     */
    public function getRecentlyAdded($course_type, $expired = false)
    {
        $mid   = request()->mid;
        $time  = time();
        $field = 'stu.course_id,stu.expire_time,c.title course_title,c.course_type,cover';
        $mod   = app(Course::class)->alias('c')->with(['cover_url'])->field($field)->join('course_student stu', 'stu.course_id=c.id')->where('stu.user_id', $mid)->where('c.course_type', $course_type);
        if ($expired) {
            $mod->where("stu.expire_time < $time");
        } else {
            $mod->whereRaw("stu.expire_time > $time OR stu.expire_time is null");
        }
        return $mod->order('stu.create_time DESC')->select()->append(['course_type_text'])->each(function ($i) use ($mid) {
                $i->finished_rate = app(LearnCourseRate::class)->where('course_id', $i->course_id)->where('user_id', $mid)->value('rate');
                $i->expire_rest   = $i->expire_time ? max(0, ceil(($i->expire_time - time()) / 86400)) : -1;
                $i->course_cover  = $i->cover_url;
                unset($i->cover_url, $i->cover, $i->expire_time);
            });
    }

    /**
     * 最近学习课程优先
     */
    public function getRecentlyLearned($course_type, $expired = false): array
    {
        $mid   = request()->mid;
        $time  = time();
        $field = 'c.id course_id,c.title course_title,c.course_type,cover,rate.rate finished_rate,stu.expire_time';

        $mod = app(CourseStudent::class)->alias('s')->leftJoin('user_learn_course_record r', 's.course_id=r.course_id AND r.user_id=' . $mid)->where('s.user_id', $mid);
        if ($expired) {
            $mod->where("s.expire_time < $time");
        } else {
            $mod->whereRaw("s.expire_time > $time OR s.expire_time is null");
        }

        $ids = $mod->order('update_time DESC')->group('s.course_id')->column('s.course_id');//->buildSql();//
        // return $ids;
        if (!count($ids)) return [];

        return app(Course::class)->alias('c')->with(['cover_url'])
            ->leftJoin('course_student stu', 'stu.course_id=c.id AND stu.user_id=' . $mid)
            ->leftJoin('user_learn_course_rate rate', 'rate.course_id=c.id AND rate.user_id=' . $mid)
            ->where('c.course_type', $course_type)->where('c.id', 'IN', $ids)
            ->field($field)->orderField('c.id', $ids)->group('c.id')
            // ->buildSql();
            ->select()->append(['course_type_text'])->each(function ($i) {
                $i->finished_rate += 0;
                $i->expire_rest   = $i->expire_time ? max(0, ceil(($i->expire_time - time()) / 86400)) : -1;
                $i->course_cover  = $i->cover_url;
                unset($i->cover_url, $i->cover, $i->expire_time);
            })->toArray();
    }

    /**
     * 获取我的学习记录列表
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date：   2020-05-18
     */
    public function getRecordList(): array
    {
        $data = $this->scope('mid')->where('course_type', 1)->order('update_time', 'DESC')
            ->append([
                'course_data',
                'section_title',
                'section_stock'
            ])->paginate(static::getListRows())->toArray();

        foreach ($data['data'] as &$item) {
            $item['expire_rest'] = app(CourseStudent::class)->getTermRest($item['course_id']);
        }
        return $data;
    }

    /**
     * 课时进度数据
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date：   2020-05-21
     */
    public function sectionRate($section_id): array
    {
        if (!request()->mid) return ['rate' => 0, 'status' => 0, 'status_text' => '未登录', 'current_time' => 0];

        $record = $this->where('section_id', $section_id)->scope('mid')->findOrEmpty();

        if ($record->isEmpty()) {
            $rate         = 0;
            $status       = 957;
            $text         = '未开始';
            $current_time = 0;
        } else if ($record->finished == 1) {
            $rate         = 100;
            $status       = 992;
            $text         = '已完成';
            $current_time = $record->current_time;
        } else {
            $rate         = 0;
            $status       = 999;
            $text         = '学习中';
            $current_time = $record->current_time;

            if ($record->section_duration) {
                $rate = floor($record->current_time * 100 / $record->section_duration);
            }
        }
        return [
            'rate'         => $rate,
            'status'       => $status,
            'status_text'  => $text,
            'current_time' => $current_time
        ];
    }

    //课程是否在学
    public function isLearning($course_id): int
    {
        $course_id = is_array($course_id) ? $course_id : (string)$course_id;

        $is_learn = $this->scope('mid')->where('course_id', 'IN', $course_id)->findOrEmpty();

        return $is_learn->isEmpty() ? 0 : 1;
    }

    /**
     * 根据课程ID查询最近在学章节信息
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date：   2020-08-04
     *
     * @param  [type]                      $course_id [description]
     */
    public function recentLearnSection($course_id)
    {
        $course_id = is_array($course_id) ? $course_id : (string)$course_id;

        $recent = $this->scope('mid')->where('course_id', 'IN', $course_id)->whereCourseType(1)->order('update_time', 'DESC')->findOrEmpty();

        $info = app(CourseSection::class)->sectionInfo($recent->section_id);

        if (!$info->isEmpty()) {
            $info->current_time = $recent->current_time;
            $info->section_data = app(CourseSection::class)->parseCourseHour($info);
        }
        return $info;
    }
}
